package br.com.puertorico.common.utils;

import java.text.MessageFormat;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.MissingResourceException;
import java.util.ResourceBundle;

/**
 * * A Class ResourceBundleUtils. Cont&eacute;m um conjunto de utilitarios para
 * manipula&ccedil;&atilde;o de arquivos de recursos.
 *
 * @author <a href="mailto:danielsudpr@gmail.com">Daniel Camargo</a>
 * @version 1.0
 */
public class ResourceBundleUtils {

	/** O campo com os bundles j&aacute; consumidos. */
	private static Map<String, ResourceBundle> BUNDLE_BUFFER;

	static {
		BUNDLE_BUFFER = new HashMap<String, ResourceBundle>();
	}

	/**
	 * M&eacute;todo de recupera&ccedil;&atilde;o de uma chave de um determinado
	 * arquivo de recursos. Caso a chave n&atilde;o exista no arquivo
	 * especificado, o valor retornado ser&aacute; o da pr&oacute;pria chave.
	 *
	 * @param locale
	 *            o locale desejado (se for null vai usar o padr&atilde;o do
	 *            sistema
	 * @param bundleName
	 *            o nome (ex: br.com.app.Messages) do arquivo de recursos.
	 * @param key
	 *            a chave para ser recuperada
	 * @param params
	 *            os parametros a serem adicionados &agrave; mensagem.
	 * @return a mensagem referente &agrave; chave.
	 */
	public static String getKey(Locale locale, String bundleName, String key,
			Object... params) {
		ResourceBundle bundle = findBundleByName(bundleName, locale);
		try {
			String msg = bundle.getString(key);
			if (params != null) {
				msg = getParameterizedMessage(msg, locale, params);
			}
			return msg;
		} catch (MissingResourceException e) {
			// assume que a mensagem eh a igual a key
			return (params != null) ? getParameterizedMessage(key, locale,
					params) : key;
		}
	}

	public static String getKey(Locale locale, ResourceBundle bundle,
			String key, Object... params) {
		try {
			String msg = bundle.getString(key);
			if (params != null) {
				msg = getParameterizedMessage(msg, locale, params);
			}
			return msg;
		} catch (MissingResourceException e) {
			return (params != null) ? getParameterizedMessage(key, locale,
					params) : key;
		}
	}

	/**
	 * M&eacute;todo de recupera&ccedil;&atilde;o do campo parameterized
	 * message.
	 *
	 * @param messageText
	 *            the message text
	 * @param messageLocale
	 *            the message locale
	 * @param params
	 *            the params
	 * @return o campo parameterized message
	 */
	private static String getParameterizedMessage(String messageText,
			Locale messageLocale, Object[] params) {
		MessageFormat messageFormat = new MessageFormat(messageText,
				messageLocale);
		messageText = messageFormat.format(params, new StringBuffer(), null)
				.toString();
		return messageText;
	}

	/**
	 * M&eacute;todo de recupera&ccedil;&atilde;o do campo class loader.
	 *
	 * @return o campo class loader
	 */
	private static ClassLoader getClassLoader() {
		ClassLoader classLoader = Thread.currentThread()
				.getContextClassLoader();
		if (classLoader == null) {
			return ResourceBundleUtils.class.getClassLoader();
		}
		return classLoader;
	}

	/**
	 * Find bundle by name.
	 *
	 * @param bundleName
	 *            the bundle name
	 * @param locale
	 *            the locale
	 * @return resource bundle
	 */
	private static ResourceBundle findBundleByName(String bundleName,
			Locale locale) {
		ResourceBundle bundle = null;
		if (BUNDLE_BUFFER.containsKey(bundleName)) {
			bundle = BUNDLE_BUFFER.get(bundleName);
			// verifica se ocorreu mudanca de locale.
			if (locale != null && bundle.getLocale().equals(locale)) {
				return bundle;
			}
		}
		bundle = ResourceBundle.getBundle(bundleName, locale, getClassLoader());
		// armazena no buffer
		BUNDLE_BUFFER.put(bundleName, bundle);
		return bundle;
	}

	public static String getKey(String bundleName, String key, Object... params) {
		return getKey(Formatador.getLocaleBrasil(), bundleName, key, params);
	}
}